package com.prd.component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.prd.constant.CacheKey;
import com.prd.enums.*;
import com.prd.mapper.UserMapper;
import com.prd.model.LoginUser;
import com.prd.model.UserDO;
import com.prd.util.CheckUtil;
import com.prd.util.CommonUtil;
import com.prd.util.JWTUtil;
import com.prd.util.JsonData;
import com.prd.vo.LoginRegisterVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author lizhaoyi
 * @date 2023/11/18 15:36
 * Description:
 */
@Service
@Slf4j
public class TelephoneLoginRegisterStrategy implements LoginRegisterStrategy{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 手机号注册登录
     * @param loginRegisterVo
     * @return
     */
    @Override
    public JsonData LoginAndRegister(LoginRegisterVo loginRegisterVo) {
        if (!CheckUtil.isPhone(loginRegisterVo.getTelephone())) {
            return JsonData.buildError("手机号不符合");
        }

        UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().eq("telephone", loginRegisterVo.getTelephone()));

        if (userDO != null) {
            //已注册则登录
            return login(loginRegisterVo, userDO);

        } else {
            //注册
            UserDO newUserDo = new UserDO();
            JsonData jsonData = register(loginRegisterVo, newUserDo);

            if (jsonData.getCode() != 0) {
                return jsonData;
            }
            //注册成功进行登录
            return login(loginRegisterVo, newUserDo);
        }
    }

    /**
     * 根据不同方式进行登录
     * @param loginRegisterVo
     * @param userDO
     * @return
     */
    private JsonData login(LoginRegisterVo loginRegisterVo, UserDO userDO) {
        BeanUtils.copyProperties(loginRegisterVo, userDO,"id","pwd","secret","isReal","isSetPwd","unionId","wxCode");
        Map<String,Object> resultMap = new HashMap<>(2);
        //一键登录
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.ONE_CLICK_LOGIN.getCode())) {
            if (userMapper.updateById(userDO) < 0) {
                return JsonData.buildError("登录信息更新异常");
            }
            //生成token
            String accessToken = getToken(userDO);
            resultMap.put("accessToken",accessToken);
            resultMap.put("userInfo",userDO);
            return JsonData.buildSuccess(resultMap);
        }
        //短信验证登录
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.MESSAGE_LOGIN.getCode())) {
            if (StringUtils.isEmpty(loginRegisterVo.getCode())) {
                return JsonData.buildError("验证码不能为空");
            }
            //校验验证码
            if (!checkCode(loginRegisterVo,true)) {
                return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
            }
            if (userMapper.updateById(userDO) < 0) {
                return JsonData.buildError("登录信息更新异常");
            }
            //登录成功,生成token
            String accessToken = getToken(userDO);
            resultMap.put("accessToken",accessToken);
            resultMap.put("userInfo",userDO);
            return JsonData.buildSuccess(resultMap);
        }
        //账号密码登录
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.ACCOUNT_PASSWORD.getCode())) {
            if (StringUtils.isEmpty(loginRegisterVo.getPwd())) {
                return JsonData.buildError("密码不能为空");
            }
            //校验密码
            String cryptPwd = Md5Crypt.md5Crypt(loginRegisterVo.getPwd().getBytes(), userDO.getSecret());
            if (!cryptPwd.equals(userDO.getPwd())) {
                return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
            }
            if (userMapper.updateById(userDO) < 0) {
                return JsonData.buildError("登录信息更新异常");
            }
            //登录成功,生成token
            String accessToken = getToken(userDO);
            resultMap.put("accessToken",accessToken);
            resultMap.put("userInfo",userDO);
            return JsonData.buildSuccess(resultMap);
        }

        return null;
    }


    /**
     * 根据不同方式进行注册
     * 不需要校验账号唯一性，存在则登录
     * @param loginRegisterVo
     * @param userDO
     * @return
     */
    private JsonData register(LoginRegisterVo loginRegisterVo, UserDO userDO) {
        BeanUtils.copyProperties(loginRegisterVo, userDO);
        userDO.setIdCardNum(null);
        userDO.setUnionId(null);
        userDO.setIsSetPwd(UserIsSetPwdTypeEnum.NO.getCode());
        userDO.setIsReal(UserAuthenticcationTypeEnum.FALSE.getCode());
        userDO.setCreateTime(LocalDateTime.now());
        userDO.setType(LoginUserTypeEnum.PHONE.getCode());
        //一键登录方式
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.ONE_CLICK_LOGIN.getCode())) {
            int rows = userMapper.insert(userDO);
            log.info("rows:{},注册成功:{}", rows, userDO.toString());
            return JsonData.buildSuccess();
        }
        //账号密码登录方式
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.ACCOUNT_PASSWORD.getCode())) {
            if (StringUtils.isEmpty(loginRegisterVo.getPwd())) {
                return JsonData.buildError("密码不能为空");
            }
            if(!CheckUtil.isValidPassword(loginRegisterVo.getPwd())) {
                return JsonData.buildError("密码长度为6以上，且同时包含数字和字母");
            }
            //设置密码 生成秘钥 盐
            userDO.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
            //密码+盐处理
            String cryptPwd = Md5Crypt.md5Crypt(loginRegisterVo.getPwd().getBytes(), userDO.getSecret());
            userDO.setPwd(cryptPwd);
            userDO.setIsSetPwd(UserIsSetPwdTypeEnum.YES.getCode());
            int rows = userMapper.insert(userDO);
            log.info("rows:{},注册成功:{}", rows, userDO.toString());
            return JsonData.buildSuccess();
        }

        //短信验证方式
        if (loginRegisterVo.getPhoneLoginRegisterType().equals(PhoneLoginRegisterTypeEnum.MESSAGE_LOGIN.getCode())) {
            //校验验证码
            if (!checkCode(loginRegisterVo,false)) {
                return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
            }
            int rows = userMapper.insert(userDO);
            log.info("rows:{},注册成功:{}", rows, userDO.toString());
            return JsonData.buildSuccess();
        }

        return null;

    }

    private String getToken(UserDO userDO) {
        LoginUser loginUser = LoginUser.builder().build();
        BeanUtils.copyProperties(userDO, loginUser);
        return JWTUtil.geneJsonWebToken(loginUser);
    }

    private Boolean checkCode(LoginRegisterVo loginRegisterVo,Boolean isDeleteKey) {
        //获取redis缓存中的验证码
        String cacheKey = String.format(CacheKey.CHECK_CODE_KEY, SendCodeEnum.USER_REGISTER, loginRegisterVo.getTelephone());
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if (!StringUtils.isEmpty(cacheValue)) {
            String cacheCode = cacheValue.split("_")[0];
            if(cacheCode.equals(cacheCode)){
                if (isDeleteKey) {
                    //删除缓存key
                    redisTemplate.delete(cacheKey);
                }
                return true;
            }
        }
        return false;
    }

}
